import { lerror, llog } from "../logger/Logger";

export interface HttpRequestOptions {
    timeout?: number;
    headers?: object;
    isJson?: boolean;   // 请求是否使用json格式
    responseType?: XMLHttpRequestResponseType;  // 响应类型
}

export interface HttpResponse {
    error: boolean; // 是否有错误
    errMsg?: string;    // 发生错误时的错误信息
    data?: any; // 响应
}

export type HttpResponseCallback = (response: HttpResponse) => void;

/**
 * Http请求
 */
export default class Http {
    private static _timeout: number = 30000;
    private static _responseType: XMLHttpRequestResponseType = "text";
    // Post请求时的默认Content-Type
    private static _postContentType: string = 'application/x-www-form-urlencoded';
    private static _headers: object = {};

    public static Init(timeout: number, headers?: object, responseType?: XMLHttpRequestResponseType, postContentType?: string) {
        this.TimeOut(timeout);
        this.Headers(headers);
        this.ResponseType(responseType);
        this.PostContentType(postContentType);
    }

    public static TimeOut(timeout: number) {
        this._timeout = timeout;
    }

    public static Headers(headers: object) {
        this._headers = headers;
    }

    public static ResponseType(responseType: XMLHttpRequestResponseType) {
        this._responseType = responseType;
    }

    public static PostContentType(postContentType: string) {
        this._postContentType = postContentType;
    }

    public static Get(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
        this._Request("GET", url, params, callback, options);
    }

    public static Post(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
        this._Request("POST", url, params, callback, options);
    }

    public static Patch(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
        params = params ?? {};
        params['_method'] = 'PATCH';
        this._Request("PATCH", url, params, callback, options);
    }

    public static Put(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
        params = params ?? {};
        params['_method'] = 'PUT';
        this._Request("PUT", url, params, callback, options);
    }

    public static Delete(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
        params = params ?? {};
        params['_method'] = 'DELETE';
        this._Request("DELETE", url, params, callback, options);
    }

    /**
     * Http请求
     * @param method 请求方法(GET/POST)
     * @param url 请求地址或URL对象
     * @param params 请求参数
     * @param callback 结果回调
     * @param options 其他选项
     */
    public static _Request(method: string, url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
        method = method.toUpperCase();

        let xhr = new XMLHttpRequest();
        if (typeof url == "string") {
            url = new URL(url);
        }

        if (params != null) {
            for (let key in params) {
                url.searchParams.set(key, params[key]);
            }
        }

        xhr.open(method, url);

        xhr.timeout = options?.timeout ?? this._timeout;
        xhr.responseType = options?.responseType ?? this._responseType;
        for (let key in options?.headers ?? this._headers) {
            xhr.setRequestHeader(key, options.headers[key]);
        }

        let requestParams: string = null;
        if (method == "POST") {
            // 处理json数据请求
            if (options?.isJson || this._postContentType == "application/json") {
                xhr.setRequestHeader("Content-Type", "application/json");
                requestParams = JSON.stringify(params);
            } else {
                xhr.setRequestHeader("Content-Type", this._postContentType);
                requestParams = url.searchParams.toString();
            }
        }

        xhr.onerror = () => {
            lerror(`请求失败, url: ${url}, params: ${JSON.stringify(params)}, status: ${xhr.status}, statusText: ${xhr.statusText}`);
            callback && callback({
                error: true,
                errMsg: `请求失败`
            });
        };

        xhr.onreadystatechange = () => {
            if (xhr.readyState != 4) {
                return;
            }

            if (xhr.status === 0 || xhr.status >= 400) {
                lerror(`请求错误, url: ${url}, params: ${JSON.stringify(params)}, status: ${xhr.status}, statusText: ${xhr.statusText}`);
                callback && callback({
                    error: true,
                    errMsg: xhr.statusText
                });
                return;
            }

            // llog(`url: ${url}, params: ${JSON.stringify(params)}, status: ${xhr.status}, statusText: ${xhr.statusText}, data: ${xhr.response}`);
            callback && callback({
                error: false,
                data: xhr.response
            });
        }

        xhr.send(requestParams);
    }
}

export function http_get(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
    Http.Get(url, params, callback, options);
}

export function http_post(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
    Http.Post(url, params, callback, options);
}

export function http_patch(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
    Http.Patch(url, params, callback, options);
}

export function http_put(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
    Http.Put(url, params, callback, options);
}

export function http_delete(url: string | URL, params?: object, callback?: HttpResponseCallback, options?: HttpRequestOptions) {
    Http.Delete(url, params, callback, options);
}